import config
import inspect

irc = None

authorized_clients = []
hosts = []
password = None
cmd_char = '~'
cmd_table = {}
info_table = {}

help_table = {
  'auth':	['<password> [command...]'],
  'load':	['<plugin1> [plugin2]...'],
  'unload':	['<plugin1> [plugin2]...'],
  'reload':	[''],
  'die':	[''],
  'say':	['<target> <message>'],
  'act':	['<target> <message>'],
  'notice':	['<target> <message>'],
  'join':	['<channel1> [channel2...'],
  'part':	['<channel1> [channel2...'],
  'nick':	['<nickname>'],
  'mode':	['[channel] <+-modes> [args]'],
  'help':	['[command]'],
  'kick':	['<channel> <target> [message]'],
  'plugins':	['']
}

def init(bot):
    global irc, cmd_table, info_table, hosts, password, cmd_char
    irc = bot
    irc.cmd.events['PRIVMSG'].subscribe(handle_privmsg)
    irc.cmd.events['PART'].subscribe(handle_part)
    irc.cmd.events['QUIT'].subscribe(handle_quit)
    irc.cmd.events['NICK'].subscribe(handle_nick)
    irc.cmd.events['KICK'].subscribe(handle_kick)

    try:
        hosts = list(config.control_hosts)
    except:
        pass
    try:
        password = config.control_password
    except:
        pass
    try:
        cmd_char = config.control_command_char
    except:
        pass

    #cmd_table['auth'] = command_auth
    cmd_table['load'] = command_load
    cmd_table['unload'] = command_unload
    cmd_table['reload'] = command_reload
    cmd_table['die'] = command_die
    cmd_table['say'] = command_say
    cmd_table['act'] = command_act
    cmd_table['notice'] = command_notice
    cmd_table['join'] = command_join
    cmd_table['part'] = command_part
    cmd_table['nick'] = command_nick
    cmd_table['mode'] = command_mode
    cmd_table['kick'] = command_kick
    cmd_table['test'] = command_test
    info_table['help'] = command_help
    info_table['plugins'] = command_plugins

    print "control.py by Matt@#liek loaded."

def handle_privmsg(sender, args):
    global irc, authorized_clients, hosts, password, cmd_table, info_table
    authorized = False
    argv = []
    handler = None

    if args[2] != irc.nickname:
        return
    if not args[0].startswith(cmd_char):
        return
    else:
        command = args[0][len(cmd_char):]
        
    argv = command.split()
    if not argv or not argv[0]:
        return
    argv[0] = argv[0].lower()

    if sender.host in hosts:
        authorized = True
    elif sender.nick in authorized_clients:
        authorized = True
    elif argv[0] == 'auth' and len(argv) > 1:
        if password and argv[1] == password:
            if len(argv) > 2:
                # Exec'ing a command - useful if not on any common channels
                _, _, command = command.split(None, 2)
                argv = argv[2:]
                authorized = True
            else:
                # Check if we're not in any common channels
                found = False
                for c in irc.chmgr.channels:
                    if sender.nick in irc.chmgr.get(c).users:
                        found = True
                        break
                if found:
                    authorized_clients.append(sender.nick)
                    authorized = True
                    irc.notice(sender.nick, "Welcome, I'll do your bidding now.")
                else:
                    irc.notice(sender.nick, "Come closer, I can't see you.")
        else:
            irc.notice(sender.nick, "Uh Uh Uh. You didn't say the magic word.")
            return
        
    if info_table.has_key(argv[0]):
        handler = info_table[argv[0]]
    elif not authorized:
        return
    if not handler and cmd_table.has_key(argv[0]):
        handler = cmd_table[argv[0]]
    if not handler:
        return

    if len(inspect.getargspec(handler)[0]) == 3:
        handler(sender, irc, argv[1:])
    else:
        handler(sender, irc, argv[1:], command)

def handle_part(sender, args):
    global irc, authorized_clients
    channel = args[2]
    check_users = []

    if sender.nick == irc.nickname:
        check_users = irc.chmgr.get(channel).users if irc.chmgr.get(channel) else []
    else:
        check_users = [sender.nick]
    
    check_auth(channel, check_users)

def handle_kick(sender, args):
    global irc, authorized_clients

    channel = args[2]
    target = args[3]
    check_users = []

    if target == irc.nickname:
        check_users = irc.chmgr.get(channel).users if irc.chmgr.get(channel) else []
    else:
        check_users = [target]

    check_auth(channel, check_users)

def check_auth(leaving_channel, users):
    for u in users:
        if u in authorized_clients:
            channels = irc.chmgr.channels
            found = False
            for ch in channels:
                if ch != leaving_channel:
                    if u in irc.chmgr.get(ch).users:
                        found = True
                        break
            if not found:
                irc.notice(u, "No longer authorized, I can't see you.")
                authorized_clients.remove(u)

def handle_quit(sender, args):
    global irc, authorized_clients

    if sender.nick in authorized_clients: authorized_clients.remove(sender.nick)


def handle_nick(sender, args):
    global irc, authorized_clients

    if sender.nick in authorized_clients: authorized_clients.replace(sender.nick, args[0])
    
    
def is_authenticated(sender):
    global hosts
    if sender.host in hosts:
        return True
    elif sender.nick in authorized_clients:
        return True
    return False

# Commands go here

def command_load(sender, irc, argv):
    plugins = argv
    if len(plugins) > 0:
        irc.notice(sender.nick, "Loading Plugin%s: %s" % ('s' if len(plugins) > 1 else '', ', '.join(plugins)))
        for plugin in plugins:
            irc.load_plugin(plugin)
    else:
        send_helpmsg(irc, sender.nick, 'load')
        return

def command_unload(sender, irc, argv):
    plugins = argv
    if len(plugins) > 0:
        irc.notice(sender.nick, "Unloading Plugin%s: %s" % ('s' if len(plugins) > 1 else '', ', '.join(plugins)))
        for plugin in plugins:
            irc.unload_plugin(plugin)
    else:
        send_helpmsg(irc, sender.nick, 'unload')
        return

def command_reload(sender, irc, argv):
    irc.notice(sender.nick, "Reloading all plugins")
    for plugin in irc.loaded_plugins:
        irc.unload_plugin(plugin)
        irc.load_plugin(plugin)

def command_die(sender, irc, argv, arg_str):
    quit_msg = arg_str[4:] if arg_str[4:] else 'Aieeeeeeeeeeeee'
    irc.notice(sender.nick, "Terminating: %s" % (quit_msg))
    irc.terminate(quit_msg)
    
def command_say(sender, irc, argv, arg_str):
    try:
        _, target, message = arg_str.split(None, 2)
    except:
        send_helpmsg(irc, sender.nick, 'say')
        return
    irc.privmsg(target, message)

def command_act(sender, irc, argv, arg_str):
    try:
        _, target, message = arg_str.split(None, 2)
    except:
        send_helpmsg(irc, sender.nick, 'act')
        return
    irc.action(target, message)
    
def command_notice(sender, irc, argv, arg_str):
    try:
	_, target, message = arg_str.split(None, 2)
    except:
	send_helpmsg(irc, sender.nick, 'notice')
	return
    irc.notice(target, message)
    
def command_join(sender, irc, argv):
    channels = argv
    if not channels:
        send_helpmsg(irc, sender.nick, 'join')
        return
    irc.notice(sender.nick, 'Joining %s' % (','.join(channels)))
    irc.joinc(','.join(channels))

def command_part(sender, irc, argv):
    channels = argv
    if not channels:
        send_helpmsg(irc, sender.nick, 'part')
        return
    irc.notice(sender.nick, 'Leaving %s' % (','.join(channels)))
    irc.part(','.join(channels))

def command_nick(sender, irc, argv):
    if not argv or not argv[0]:
        send_helpmsg(irc, sender.nick, 'nick')
        return
    new_nick = argv[0]
    irc.notice(sender.nick, 'Changing nickname to %s' % (new_nick))
    irc.nick(new_nick)

def command_mode(sender, irc, argv):
    modes = argv
    if not modes or not modes[0]:
        send_helpmsg(irc, sender.nick, 'mode')
        return
    if modes[0][0] == '+' or modes[0][0] == '-':
        irc.usermode(irc.nickname, modes[0])
        irc.notice(sender.nick, 'Setting mode: %s' % (modes[0]))
    elif len(modes) > 1:
        irc.notice(sender.nick, 'Setting mode on %s: %s' % (argv[0], ' '.join(argv[1:])))
        irc.mode(argv[0], argv[1], ' '.join(argv[2:]))
    else:
        send_helpmsg(irc, sender.nick, 'mode')
        
def command_kick(sender, irc, argv, arg_str):
    kick_args = arg_str.split(None, 3)
    if len(kick_args) < 3:
	send_helpmsg(irc, sender.nick, 'kick')
	return
    irc.notice(sender.nick, "Kicking %s from %s (%s)" % (kick_args[2], kick_args[1], kick_args[3] if len(kick_args) > 3 else ""))
    irc.kick(kick_args[1], kick_args[2], kick_args[3] if len(kick_args) > 3 else None)

def command_help(sender, irc, argv):
    global help_table
    if argv and argv[0]:
      command = argv[0].lower()
      if help_table.has_key(command):
	send_helpmsg(irc, sender.nick, command, True)
	return
    cmds = help_table.keys()
    cmds.sort()
    irc.notice(sender.nick, "Available commands: %s" % (", ".join(cmds)))

def command_test(sender, irc, argv):
#    config.channels.append('#test')
#    irc.notice(sender.nick, 'Added channel')
    pass

def command_plugins(sender, irc, argv):
    my_list = []
    for plugin in irc.loaded_plugins:
        p = plugin.replace('plugin.', '')
        my_list.append(p)
    irc.notice(sender.nick, "Loaded Plugins: %s" % (', '.join(my_list))) 

def send_helpmsg(irc, target, command, full = False):
    global help_table
    if not irc or not target:
        return
    if help_table.has_key(command):
	irc.notice(target, "\002%s%s\002: %s" % (cmd_char, command, help_table[command][0]))
